Go の functional option pattern
default 値を設定できる
省略 (default 値が設定されるべき) と 0 値 (0 値が設定されるべき) とを混同しない
引數として optional である事に pointer を使はなくてよいので、引數として optional である事と値として optional である (零値と nil とを區別する) 事とを區別できる
optional な引數が增えても函數の本體が長くならない
他の手法では、引數で値を受け取ってそれを default 値で上書きする動きをする。functional option pattern では、default 値を呼び出される側が用意してそれを呼び出し側に變更させる
code:go
type FOpt struct {
Opt1 int
Opt2 string
}
func FOpt1(i int) func(*FOpt) {
return func(o *FOpt) { o.Opt1 = i }
}
func FOpt2(s string) func(*FOpt) {
return func(o *FOpt) { o.Opt2 = s }
}
func F(arg1 Arg1, options ...func(*FOpt)) {
option := FOpt{
Opt2: "default value", // default 値を設定できる
}
for _, f := range options {
f(&option)
}
// do something using option
}
func main() {
// 省略できる
F(arg1)
// 設定できる。設定する順番も自由
F(arg1, func(o *FOpt) { o.Opt1 = 42; o.Opt2 = "spam" })
// wrapper 函數
F(arg1, FOpt1(42))
F(arg1, FOpt1(42), FOpt2("spam"))
}
他のやり方
optional な引數の數だけ函數を定義する
code:go
func F(arg1 Arg1, opt1 int, opt2 string) {
// do something
}
func FWithDefaultOpt1(arg1 Arg1, opt2 string) {
F(arg1, 0, opt2)
}
func FWithDefaultOpt2(arg1 Arg1, opt1 int) {
F(arg1, opt1, "default value")
}
func FWithDefaultOpt1WithDefaultOpt2(arg1 Arg1) {
F(arg1, 0, "default value")
}
組み合はせ爆發
値の pointer を引數で受け取る
code:go
func F(arg1 Arg1, opt1 *int, opt2 *string) {
if opt1 == nil {
v := 0
opt1 = &v
}
if opt2 == nil {
v := "default value"
opt2 = &v
}
// do something
}
fun main() {
opt1 := 42
F(arg1, &opt1, nil)
}
optional 引數の個數を增やすと呼び出し側が compile error になる
pointer を渡すのは呼び出しが不便
引數が意味ではなく位置で指定されてゐるので、省略する引數も nil を明示しなければならない
optional 引數が增えると函數の本體が長くなる
option を表す struct を引數で受け取る
code:go
type FOpt struct {
Opt1 *int
Opt2 *string
}
func F(arg1 Arg1, option FOpt) {
if option.Opt1 == nil {
v := 0
option.Opt1 = &v
}
if option.Opt2 == nil {
v := "default value"
option.Opt2 = &v
}
// do something
}
func main() {
opt1 := 42
F(arg1, FOpt{ Opt1: &opt1 })
}
pointer を渡すのは呼び出しが不便
optional 引數が增えると函數の本體が長くなる